package stdx;

import java.util.List;
import java.util.ArrayList;

public class CacheList<T>{
	@FunctionalInterface
	public interface LoadFunc{
		List apply(CacheList self);
	}

	@FunctionalInterface
	public interface FindFunc<T>{
		boolean apply(T item);
	}

	@FunctionalInterface
	public interface EachFunc<T>{
		void apply(T item);
	}

	byte inited = 0;
	LoadFunc loader = null;
	ArrayList<T> list = new ArrayList<>();

	public T back(){
		synchronized(list){
			int len = list.size();
			return len > 0 ? list.get(len - 1) : null;
		}
	}
	public T front(){
		synchronized(list){
			int len = list.size();
			return len > 0 ? list.get(0) : null;
		}
	}
	public int size(){
		synchronized(list){
			return list.size();
		}
	}
	public boolean isEmpty(){
		synchronized(list){
			return list.isEmpty();
		}
	}

	public List<T> get(){
		if (inited == 0) update();

		List<T> res = new ArrayList<>();

		synchronized(list){
			res.addAll(list);
		}

		return res;
	}
	@SuppressWarnings("unchecked")
	public CacheList update(){
		inited = 1;

		List tmp = loader.apply(this);

		synchronized(list){
			list.clear();
			list.addAll(tmp);
		}

		return this;
	}
	@SuppressWarnings("unchecked")
	public T find(FindFunc func){
		if (inited == 0) update();

		synchronized(list){
			for (T item : list){
				if (func.apply(item)) return item;
			}
		}

		return null;
	}
	@SuppressWarnings("unchecked")
	public void each(EachFunc func){
		if (inited == 0) update();

		synchronized(list){
			for (T item : list){
				func.apply(item);
			}
		}
	}
	public CacheList(LoadFunc loader){
		this(5000L, loader);
	}
	public CacheList(long period, LoadFunc loader){
		TaskQueue.WorkItem workitem = new TaskQueue.WorkItem(){
			@Override
			public void run(){
				try{
					update();
				}
				catch (Exception e){
					e.printStackTrace();
				}
				this.setDelay(period);
				TaskQueue.Instance().push(this);
			}
		};

		this.loader = loader;
		workitem.setDelay(period);
		TaskQueue.Instance().push(workitem);
	}
}
